:-module(dd,[stamp_to_divine/3,to_chinese/2,from_chinese/2,get_jieqi_by_year_and_ording/3,get_jieqi_by_stamp/2,
	     five_mouse/3,five_tiger/3
	    ]).
:-use_module('de.pro').

to_chinese(Y-M-D,CY-CM-CD-L):-
	start_year(Sy),
	start(StartStamp),
	date_time_stamp(date(Y,M,D,0,0,0,0,_,_),ThisStamp),
	D1 is floor((ThisStamp - StartStamp) / (24 * 3600)),
	Index is Y - Sy,
	befor_days_of_year(Index,D2),
	(D1 >= D2 -> CI = Index ; CI is Index - 1),
	get_info(CI,Info),
	befor_days_of_year(CI,D3),
	D4 is D1 - D3,
	M1 is D4 // 30 + 1,
	befor_days_of_month_ording(Info,M1,D5),
	D6 is D4 - D5,
	nth1(M1,Info.bits,D7),
	D8 is 29 + D7,
	(D6 >= D8 -> M2 is M1 + 1, CD is D6 - D8 + 1;
	 M2 = M1, CD is D6 + 1),
	month_order(CM,L,Info.leap,M2),
	CY is Sy + CI.

from_chinese(CY-CM-CD-L,Y-M-D):-
	start_year(Sy),
	Index is CY - Sy,
	get_info(Index,Info),
	month_order(CM,L,Info.leap,Ord),
	befor_days_of_month_ording(Info,Ord,D1),
	befor_days_of_year(Index,D2),
	Days is D1 + D2 + CD - 1,
	start(StartStamp),
	Stamp is StartStamp + Days * 24 * 3600,
	stamp_date_time(Stamp,date(Y,M,D,_,_,_,0,_,_),0).

get_jieqi_by_year_and_ording(Y,O,R):-
	O > 23,
	Y1 is Y + 1,
	O1 is O - 24,
	get_jieqi_by_year_and_ording(Y1,O1,R).

get_jieqi_by_year_and_ording(Y,O,R):-
	O < 0,
	Y1 is Y - 1,
	O1 is O + 24,
	get_jieqi_by_year_and_ording(Y1,O1,R).

get_jieqi_by_year_and_ording(Y,O,R):-
	between(0,23,O),
	start_year(Sy),
	Index is Y - Sy,
	lichun(LI),
	nth0(Index,LI,Lichun),
	date_time_stamp(date(Y,2,4,0,0,0,0,_,_),Stamp),
	solar(SL),
	nth0(O,SL,Solar),
	R is Stamp + Lichun + Solar.

get_jieqi_by_stamp(Stamp,R):-
	stamp_date_time(Stamp,date(Y,M,_,_,_,_,0,_,_),0),
	between(0,2,OD),
	O1 is 2 * M - 5 + OD,
	O2 is O1 + 1,
	get_jieqi_by_year_and_ording(Y,O1,R1),
	get_jieqi_by_year_and_ording(Y,O2,R2),
	R1 =< Stamp, Stamp < R2,
	(
	 O1 < 0 -> O3 is O1 + 24, Y1 is Y - 1;
	 Y1 = Y, O3 = O1
	),
	StampDiff is Stamp - R1,
	R = _{year:Y1,order:O3,diff:StampDiff}.

stamp_to_divine(Stamp,TZ,Divine):-
	stamp_date_time(Stamp,date(D1,D2,D3,D4,D5,D6,TZ,_,_),TZ),
	to_chinese(D1-D2-D3,C1-C2-C3-C4),
	year_ganzhi_yuan(C1,Year,Yuan),
	Month is Year mod 5 * 12 + C2 + 1,
	get_jieqi_by_stamp(Stamp,Jieqi),
	year_ganzhi_yuan(Jieqi.year,JQYear,JQYuan),
	JQMonth is JQYear mod 5 * 12 + Jieqi.order div 2 + 2,
	(Jieqi.order > 20 -> DZY is Jieqi.year + 1; DZY = Jieqi.year),
	year_ganzhi_yuan(DZY,DZYear,DZYuan),
	Days is floor(Stamp - TZ) div 86400,
	Date is (Days + 17) mod 60,
	Su28 is (Days + 7) mod 28,
	Jianchu is (Date - JQMonth) mod 12,
	Hour is (Date mod 5 * 12 + (D4 + 1) div 2) mod 60,
	Divine = _{
		   gongli: D1-D2-D3,
		   nongli: _{year:C1,month:C2,date:C3,leap:C4},
		   time: D4:D5:D6,
		   su28: Su28,
		   jieqi: Jieqi,
		   jianchu: Jianchu,
		   yuan: _{base:Yuan, jieqi: JQYuan,dongzhi: DZYuan},
		   stamp: Stamp,
		   timezone: TZ,
		   ganzhi: _{
			     year: _{nongli:Year,jieqi:JQYear,dongzhi:DZYear},
			     month:_{nongli:Month,jieqi:JQMonth},
			     date: Date, hour: Hour
			     }
		   }.


year_ganzhi_yuan(Year,GZ,Yuan):-
	GZ is (Year - 4) mod 60,
	Yuan is ((Year - 64) mod 180) div 60.
		 

get_info(Index,Result):-
	info(INFO),
	nth0(Index,INFO,K),
	Leap is K >> 16,
	(Leap > 0 -> Ms = 13; Ms = 12),
	M is K /\ 0x1FFF,
	num2bin(M,Ms,Bits),
	Result = _{leap:Leap,bits:Bits,mons:Ms}.

% 农历某年（不含该年）之前的天数
befor_days_of_year(0,A,A).
befor_days_of_year(Index,Tail,Result):-
	Index > 0,
	NewIndex is Index - 1,
	get_info(NewIndex,Info),
	sum_list(Info.bits,S1),
	S2 is S1 + 29 * Info.mons,
	NewTail is Tail + S2,
	befor_days_of_year(NewIndex,NewTail,Result).
befor_days_of_year(Index,Result):-
	befor_days_of_year(Index,0,Result).

% 某月序之前的天数，不含此月
befor_days_of_month_ording(Info,Mo,Days):-
	append(L1,_,Info.bits),
	M is Mo - 1,
	length(L1,M),
	sum_list(L1,S1),
	Days is S1 + M * 29.
	
month_order(M,0,0,M):-!.
month_order(M,0,LM,M):-
	M < LM,!.	
month_order(M,0,M,M):-!.
month_order(M,L,LM,O):-
	plus(M,1,O),!,
	(M = LM -> L = 1; L = 0).




				% 每一年的农历信息
info([
    0xA4B,0x5164B,  0x6A5,  0x6D4,0x415B5,  0x2B6,  0x957,0x2092F,  0x497,0x60C96,
    0xD4A,  0xEA5,0x50DA9,  0x5AD,  0x2B6,0x3126E,  0x92E,0x7192D,  0xC95,  0xD4A,
    0x61B4A,  0xB55,  0x56A,0x4155B,  0x25D,  0x92D,0x2192B,  0xA95,0x71695,  0x6CA,
    0xB55,0x50AB5,  0x4DA,  0xA5B,0x30A57,  0x52B,0x8152A,  0xE95,  0x6AA,0x615AA,
    0xAB5,  0x4B6,0x414AE,  0xA57,  0x526,0x31D26,  0xD95,0x70B55,  0x56A,  0x96D,
    0x5095D,  0x4AD,  0xA4D,0x41A4D,  0xD25,0x81AA5,  0xB54,  0xB6A,0x612DA,  0x95B,
    0x49B,0x41497,  0xA4B,0xA164B,  0x6A5,  0x6D4,0x615B4,  0xAB6,  0x957,0x5092F,
    0x497,  0x64B,0x30D4A,  0xEA5,0x80D65,  0x5AC,  0xAB6,0x5126D,  0x92E,  0xC96,
    0x41A95,  0xD4A,  0xDA5,0x20B55,  0x56A,0x7155B,  0x25D,  0x92D,0x5192B,  0xA95,
    0xB4A,0x416AA,  0xAD5,0x90AB5,  0x4BA,  0xA5B,0x60A57,  0x52B,  0xA93,0x40E95
     ]).

 % 每年立春距离当年标准时间2-4的秒数
 lichun([
    30017 ,50790 ,72022 ,92978 ,27410 ,49100 ,70207 ,90987 ,25728 ,46273 ,
    67242 ,88165 ,22161 ,43421 ,64126 ,84560 ,19537 ,40502 ,61830 ,83256 ,
    17389 ,38917 ,60008 ,80579 ,15566 ,36237 ,57024 ,78124 ,12174 ,33649 ,
    54810 ,75176 ,9956  ,30645 ,51459 ,72718 ,6880  ,28153 ,49333 ,69791 ,
    4947  ,26243 ,47267 ,68698 ,2769  ,23872 ,45051 ,65246 ,-65   ,20746 ,
    41126 ,62414 ,-3346 ,18007 ,39553 ,59970 ,-5193 ,16020 ,36739 ,58170 ,
    -7474 ,13530 ,34783 ,55126 ,-10090,11262 ,31900 ,52970 ,-12768,8041  ,
    29305 ,49697 ,-15769,5456  ,25971 ,47273 ,-17882,3411  ,25023 ,45623 ,
    -19869,1445  ,21919 ,42972 ,-22617,-1964 ,19090 ,39621 ,-25814,-4333 ,
    16372 ,37338 ,-27999,-7009 ,14300 ,35153 ,-30365,-9101 ,11647 ,32586 ,
    -32487,-11369,9734  ,30407 ,-35393,-14294,6353  ,27048 ,-38381,-17520,
    3467  ,24504 ,-40738,-19165,1857  ,22757 ,-42542,-21413,-467  ,20349
	]).

 % 每个节气距离立春的秒数
 solar([
    0,1281594,2571382,3871171,5182005,6504322,7837658,9180883,10532032,11888645,
    13247759,14606280,15961112,17309470,18649066,19978229,21296097,22602541,
    23898266,25184605,26463560,27737495,29009169,30281379,31556925
       ]).

start(Stamp):-
	date_time_stamp(date(1921,2,8,0,0,0,0,_,_),Stamp). % 1921正月初一 = 2月8日
start_year(1921).

five_mouse(G,Z,GZ):-
	GZ is G mod 5 * 12 + Z.

five_tiger(G,Z,GZ):-
	Z > 1 -> five_mouse(G,Z,GZ);
	G1 is G + 1, five_mouse(G1,Z,GZ).
